﻿using Microsoft.Extensions.Hosting;
using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.Threading.Tasks;

/*********************************************************
 * 命名空间 Simple.WindowsServer
 * 接口名称 SimpleServer
 * 开发人员：11920
 * 创建时间：2023/4/24 9:48:16
 * 描述说明：
 * 更改历史：
 * 
 * *******************************************************/
namespace Simple.WindowsServer
{
	public class SimpleHostLifeTime: ServiceBase, IHostLifetime
	{
		private readonly TaskCompletionSource<object> _delayStart = new TaskCompletionSource<object>(TaskCreationOptions.RunContinuationsAsynchronously);
		private readonly ManualResetEventSlim _delayStop = new ManualResetEventSlim();

		public SimpleHostLifeTime(IHostEnvironment environment, IHostApplicationLifetime applicationLifetime)
		{
			CanShutdown = true;
			this.Environment = environment;
			this.ApplicationLifetime = applicationLifetime;
		}



		private IHostApplicationLifetime ApplicationLifetime { get; }
		private IHostEnvironment Environment { get; }

		public Task WaitForStartAsync(CancellationToken cancellationToken)
		{
			cancellationToken.Register(() => _delayStart.TrySetCanceled());
			ApplicationLifetime.ApplicationStarted.Register(() =>
			{

			});
			ApplicationLifetime.ApplicationStopping.Register(() =>
			{

			});
			ApplicationLifetime.ApplicationStopped.Register(() =>
			{
				_delayStop.Set();
			});

			Thread thread = new Thread(Run);
			thread.IsBackground = true;
			thread.Start(); // Otherwise this would block and prevent IHost.StartAsync from finishing.

			return _delayStart.Task;
		}

		private void Run()
		{
			try
			{
				Run(this); // This blocks until the service is stopped.
				_delayStart.TrySetException(new InvalidOperationException("Stopped without starting"));
			}
			catch (Exception ex)
			{
				_delayStart.TrySetException(ex);
			}
		}

		public Task StopAsync(CancellationToken cancellationToken)
		{
			// Avoid deadlock where host waits for StopAsync before firing ApplicationStopped,
			// and Stop waits for ApplicationStopped.
			Task.Run(Stop);
			return Task.CompletedTask;
		}

		// Called by base.Run when the service is ready to start.
		protected override void OnStart(string[] args)
		{
			_delayStart.TrySetResult(null);
			base.OnStart(args);
		}

		// Called by base.Stop. This may be called multiple times by service Stop, ApplicationStopping, and StopAsync.
		// That's OK because StopApplication uses a CancellationTokenSource and prevents any recursion.
		protected override void OnStop()
		{
			ApplicationLifetime.StopApplication();
			// Wait for the host to shutdown before marking service as stopped.
			_delayStop.Wait(10);
			base.OnStop();
		}

		protected override void OnShutdown()
		{
			ApplicationLifetime.StopApplication();
			// Wait for the host to shutdown before marking service as stopped.
			_delayStop.Wait(10);
			base.OnShutdown();
		}

		protected override void Dispose(bool disposing)
		{
			if (disposing)
			{
				_delayStop.Set();
			}

			base.Dispose(disposing);
		}
	}
}
